package com.dcivision.dms.client.parser;

/*
 * @(#)ACMEIndexParser.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the idential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */

import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import com.dcivision.dms.client.GlobalIndexTransformation;

/**
 * ACMEIndexParser -- an application that reads an image index file
 * exported from ACME using xml file format.
 * <p>
 * ACME index files have this format:<pre>
 * <descriptor type="Document" layout="1.0">
 *  <set status="0">
 *    <pri_attributes object_handle="" baseclass="Document" class="GOC_MPF" formtype="MEMAPP" l
 *    abel="MEMAPP" creator="scan1" datetimecreated="2003-01-02 12:14:07" indexer="index1"
 *     datetimeindexed="02-01-2003 12:48:22" verifier="" datetimeverified=""/>
 *    <properties>
 *      <propertyset>
 *        <property id="Name" name="Name">//LHAN,JFPN SHEII</property>
 *        <property id="HKID" name="HKID">Membership Application Forni</property>
 *        <property id="EmployerName" name="EmployerName">Membership Application Forni</property>
 *        <property id="FormType" name="FormType">I NNRSEETM</property>
 *      </propertyset>
 *    </properties>
 *    <pages CoverPages="T" CoverPage="T">
 *      <page label="Page 1">A20030102121805908.tif</page>
 *    </pages>
 *  </set>
 * </descriptor>
 * </pre>
 *
    @author          Zoe Shum
    @company         DCIVision Limited
    @creation date   06/09/2003
    @version         $Revision: 1.21.2.1 $
 */
public class ACMEIndexParser implements IndexParser {

  public static final String REVISION = "$Revision: 1.21.2.1 $";

  ContentHandler handler;
  Hashtable confTable = new Hashtable();

  // no namespaces required
  String nsu = ""; // NamespaceURI
  String rootElement = "descriptor";
  String indent = "\n    "; // for readability!

  String loginName="";
  String loginPwd="";
  String rootID="";
  String parentID="";
  
  private static final Log log = LogFactory.getLog(ACMEIndexParser.class);
  public void setConfigTable(Hashtable configTable) {
    //System.out.println("init config table.....");
    this.confTable = configTable;
  }

  public String getLoginName(){
    return this.loginName;
  }

  public String getLoginPwd(){
    return this.loginPwd;
  }

  public String getRootID(){
    return this.rootID;
  }

  public String getParentID(){
    return this.parentID;
  }

  /** Parse the input */
  public void parse(InputSource input) throws IOException, SAXException {
    try { // Get an efficient reader for the file

      // Create an Document node as the root for the output.
      DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
      org.w3c.dom.Document indexFile = docBuilder.parse(input);

      if (handler == null) {
        throw new SAXException("No content handler");
      }
      // Start the document, and write its root element
      handler.startDocument();
      AttributesImpl elementAtt = new AttributesImpl();
      elementAtt.addAttribute("", "", "class", "", "Document");
      //elementAtt.addAttribute("","","name_prefix","","JOS");
      elementAtt.addAttribute("", "", "type", "", ( (String)confTable.get(IndexParser.SCAN_UPLOAD_FILE_EXTEN)).trim());
      elementAtt.addAttribute("", "", "scan_method", "", ( (String)confTable.get(IndexParser.SCAN_METHOD)).trim());
      elementAtt.addAttribute("", "", "parent_id", "", ( (String)confTable.get(IndexParser.DMS_PARENT_ID)).trim());
      elementAtt.addAttribute("", "", "root_id", "", ( (String)confTable.get(IndexParser.DMS_ROOT_ID)).trim());

      //Get datetimecreated from index file as the create date
      String datetimecreated = "";
      String createBy = "";
      String udfName = "";
      NodeList nl = indexFile.getElementsByTagName("pri_attributes");
      for (int i = 0; i < nl.getLength(); i++) {
        Element targetNode = (Element)nl.item(i);
        datetimecreated = targetNode.getAttribute("datetimecreated");
        //System.out.println("datetimecreated = "+ datetimecreated);
        createBy = targetNode.getAttribute("creator");
        udfName = targetNode.getAttribute("class");
        //System.out.println("ame = "+ udfName);
      }
      elementAtt.addAttribute("", "", "create_date", "", datetimecreated);
      elementAtt.addAttribute("", "", "create_by", "", createBy);
      Attributes atts = new AttributesImpl(elementAtt);
      handler.startElement(nsu, rootElement, rootElement, atts);

      //className user for document/folder name creation
      writeTag("class_name", "StandardDocumentAnalyzer.class", new AttributesImpl());
      writeTag("description", "", new AttributesImpl());
      writeTag("reference_no", "", new AttributesImpl());

      elementAtt.clear();
      elementAtt.addAttribute("", "", "name", "", udfName);
      atts = new AttributesImpl(elementAtt);
      writeStartTag("document_profile", "", atts);

      //attribute
      String fieldName = "";
      String fieldType = "";
      String fieldValue = "";
      NodeList d = indexFile.getElementsByTagName("property");
      for (int i = 0; i < d.getLength(); i++) {
        fieldValue = "";
        Element targetNode = (Element)d.item(i);
        fieldName = targetNode.getAttribute("id");
        //get the text as subnode handling
        Node subnode = d.item(i).getFirstChild();
        if (subnode != null) {
          fieldValue = subnode.getNodeValue();
        }
        //System.out.println("fieldName = " + fieldName);
        //System.out.println("fieldValue = " + fieldValue);
        elementAtt.clear();
        elementAtt.addAttribute("", "", "name", "", fieldName);
        elementAtt.addAttribute("", "", "type", "", fieldType);
        atts = new AttributesImpl(elementAtt);
        writeTag("field", fieldValue, atts);
      }
      writeEndTag("document_profile");
      /* End document Profile section*/

      /* Pages section*/
      int pagesCount = 0;
      NodeList pagesList = indexFile.getElementsByTagName("page");
      if (pagesList != null)
        pagesCount = pagesList.getLength();
      elementAtt.clear();
      elementAtt.addAttribute("", "", "count", "", new Integer(pagesCount).toString());
      atts = new AttributesImpl(elementAtt);
      writeStartTag("pages", "", atts);

      String label = "";
      for (int i = 0; i < pagesList.getLength(); i++) {
        Element targetNode = (Element)pagesList.item(i);
        label = targetNode.getAttribute("label");
        //get the text as subnode handling
        Node subnode = pagesList.item(i).getFirstChild();
        if (subnode != null) {
          fieldValue = subnode.getNodeValue();
          //System.out.println("value " + subnode.getNodeValue());
        }
        elementAtt.clear();
        elementAtt.addAttribute("", "", "label", "", label);
        atts = new AttributesImpl(elementAtt);
        writeTag("page", fieldValue, atts);
      }
      writeEndTag("pages");
      /* End Pages section*/

      /* Index Detail section*/
      int indexFileCount = 1;
      elementAtt.clear();
      elementAtt.addAttribute("", "", "file_count", "", new Integer(indexFileCount).toString());
      atts = new AttributesImpl(elementAtt);
      writeStartTag("index_detail", "", atts);

      String value = "all";
      fieldValue = (String)confTable.get(IndexParser.XML_INDEX_FILENAME);
      fieldValue = fieldValue.substring(1, fieldValue.length());  //clear up the char '\' for presentation
      elementAtt.clear();
      elementAtt.addAttribute("", "", "value", "", value);
      atts = new AttributesImpl(elementAtt);
      writeTag("file", fieldValue, atts);

      writeEndTag("index_detail");
      /* End Index Detail section*/

      /* Full Text section*/
      atts = new AttributesImpl();
      fieldValue = (String)confTable.get(IndexParser.FULL_TEXT);
      writeTag("full_text", fieldValue, atts);

      /* End Full Text section*/

      handler.ignorableWhitespace("\n".toCharArray(),
                                  0, // start index
                                  1 // length
                                  );
      handler.endElement(nsu, rootElement, rootElement);
      handler.endDocument();

    } catch (Exception e) {
      log.error(e, e);
    }
  }

  void writeTag(String tagName, String value, Attributes atts) throws SAXException {
    handler.ignorableWhitespace(indent.toCharArray(),
                                0, // start index
                                indent.length()
                                );
    handler.startElement(nsu, tagName, tagName /*"qName"*/, atts);

    handler.characters(value.toCharArray(),
                       0,
                       value.length());
    handler.endElement(nsu, tagName, tagName);
  }

  void writeStartTag(String tagName, String value, Attributes atts) throws SAXException {
    handler.ignorableWhitespace(indent.toCharArray(),
                                0, // start index
                                indent.length()
                                );

    handler.startElement(nsu, tagName, tagName, atts);
  }

  void writeEndTag(String tagName) throws SAXException {
    handler.ignorableWhitespace(indent.toCharArray(),
                                0, // start index
                                indent.length()
                                );
    handler.endElement(nsu, tagName, tagName);
  }

  /** Backup All the target upload files and index files. */
  public void backupAllFiles(String actionStatus) {
    String backupDir = (String)confTable.get(IndexParser.BACKUP_DIR);
    String sourceDir = (String)confTable.get(IndexParser.SOURCE_DIR);
    String errorDir = (String)confTable.get(IndexParser.ERROR_DIR);

    //Target Dir depends on the action is success or error
    String targetDir = backupDir;
    if (GlobalIndexTransformation.STATUS_ERROR.equals(actionStatus)) {
      targetDir = errorDir;
    }
    File backup = new File(targetDir);
    if (!backup.exists()) {
      backup.mkdirs();
    }
    //System.out.println("Target file copy to Dir............. " + targetDir);
    String uploadFilePath = (String)confTable.get(IndexParser.UPLOAD_FILE_PATH);
    this.copyAndDeleteFile(sourceDir, targetDir, uploadFilePath);

    String oldIndexFilePath = (String)confTable.get(IndexParser.OLD_INDEX_FILE_PATH);
    this.copyAndDeleteFile(sourceDir, targetDir, oldIndexFilePath);

    String xmlIndexFilePath = (String)confTable.get(IndexParser.XML_INDEX_FILE_PATH);
    this.copyAndDeleteFile(sourceDir, targetDir, xmlIndexFilePath);
    if (GlobalIndexTransformation.STATUS_ERROR.equals(actionStatus)) {
      this.deleteFile(targetDir, xmlIndexFilePath);
    }

    String fullTextPath = (String)confTable.get(IndexParser.FULL_TEXT_FILE_PATH);
    this.copyAndDeleteFile(sourceDir, targetDir, fullTextPath);
  }

  public void copyAndDeleteFile(String sourceDir, String backupDir, String targetFilePath) {
    String data = "";
    String fileName = "";
    try {
      File inputFile = new File(targetFilePath);
      File ofile = new File(targetFilePath);
      fileName = ofile.getName();
      if (ofile.exists()) {

        java.io.FileInputStream fis = new java.io.FileInputStream(inputFile);
        byte[] content = new byte[1024 * 1024];

        String newFileAbsPath = backupDir + File.separator + fileName;
        //System.out.println("new file = " + newFileAbsPath);
        File f = new File(newFileAbsPath);
        if (!f.exists()) {
          f.createNewFile();
          java.io.FileOutputStream fos = new java.io.FileOutputStream(f);

          int bufferSize = 8192;
          byte[] buffer = new byte[bufferSize];
          int length = -1;

          while ( (length = fis.read(buffer, 0, bufferSize)) != -1) {
            fos.write(buffer, 0, length);
          }
          fos.flush();
          fos.close();
          fis.close();

        }
        if (f.exists()) {
          fis.close();
          ofile.delete();
        }
      }
    } catch (Exception e) {
      log.error(e, e);
    }
  }

  public void deleteFile(String dir, String targetFilePath) {

    String fileName = "";
    try {
      File file = new File(targetFilePath);
      fileName = file.getName();
      if (file.exists()) {
        file.delete();
      }
    } catch (Exception e) {
      log.error(e, e);
    }
  }

  /** Allow an application to register a content event handler. */
  public void setContentHandler(ContentHandler handler) {
    this.handler = handler;
  }

  /** Return the current content handler. */
  public ContentHandler getContentHandler() {
    return this.handler;
  }

  //=============================================
  // IMPLEMENT THESE FOR A ROBUST APP
  //=============================================
  /** Allow an application to register an error event handler. */
  public void setErrorHandler(ErrorHandler handler) {}

  /** Return the current error handler. */
  public ErrorHandler getErrorHandler() {
    return null;
  }

  //=============================================
  // IGNORE THESE
  //=============================================
  /** Parse an XML document from a system identifier (URI). */
  public void parse(String systemId) throws IOException, SAXException {}

  /** Return the current DTD handler. */
  public DTDHandler getDTDHandler() {
    return null;
  }

  /** Return the current entity resolver. */
  public EntityResolver getEntityResolver() {
    return null;
  }

  /** Allow an application to register an entity resolver. */
  public void setEntityResolver(EntityResolver resolver) {}

  /** Allow an application to register a DTD event handler. */
  public void setDTDHandler(DTDHandler handler) {}

  /** Look up the value of a property. */
  public Object getProperty(String name) {
    return null;
  }

  /** Set the value of a property. */
  public void setProperty(String name, Object value) {}

  /** Set the state of a feature. */
  public void setFeature(String name, boolean value) {}

  /** Look up the value of a feature. */
  public boolean getFeature(String name) {
    return false;
  }
}